package com.ctrip.corp.obt.shard.infrastructure.apollo;

import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.DataShardContext;
import com.ctrip.corp.obt.shard.core.ShardDataSource;
import com.ctrip.corp.obt.shard.domain.ShardDataSourceMeta;
import com.ctrip.corp.obt.shard.domain.gateway.DataShardSourceGateway;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author marco.zheng
 * @version 1.0
 * @date 2022/03/15
 * @desc apollo 数据网关
 * @see
 * @since 1.0
 */
@Slf4j
public class ApolloDataShardSourceGateway implements DataShardSourceGateway {

    private final ApolloClient apolloClient;

    public ApolloDataShardSourceGateway(ApolloClient apolloClient) {
        this.apolloClient = apolloClient;
    }

    @Override
    public Set<ShardDataSource> getAllSource() {
        List<String> tenantIdSet = apolloClient.getTenantList();
        return getSources(tenantIdSet);
    }

    @Override
    public Set<ShardDataSource> getSourceByTenantIds(Set<String> tenantIds) {
        List<String> existTenantIdList = apolloClient.getTenantList();
        List<String> finalTenantIdSet =
            tenantIds.stream().filter(existTenantIdList::contains).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(finalTenantIdSet)) {
            return Collections.emptySet();
        }
        return getSources(finalTenantIdSet);
    }

    private Set<ShardDataSource> getSources(List<String> tenantIdSet) {
        if (CollectionUtils.isEmpty(tenantIdSet)){
            return Collections.emptySet();
        }
        Set<ShardDataSource> apolloDataSourceSet = new HashSet<>(tenantIdSet.size());
        tenantIdSet.stream().filter(StringUtils::isNotBlank).forEach(tenantId -> {
            try {
                // 中粮需要将该tenantId回写，不然会报 tenant is empty
                DataShardContext.setTenantId(tenantId);
                ShardDataSource dataSource = new ShardDataSource(tenantId, "apollo");
                ShardDataSourceMeta meta = new ShardDataSourceMeta(apolloClient.getDriverClassName(), apolloClient.getDatabaseUrl(),
                        apolloClient.getDatabaseUsername(), apolloClient.getDatabasePassword(), Collections.emptyList());
                dataSource.setMetas(Collections.singletonList(meta));
                apolloDataSourceSet.add(dataSource);
            } catch (NoClassDefFoundError ex) {
                // properly no MultiTenantConfigService was found, cause no below jar was found, don't need to do
                // anything
                // ``````````````````````````````````````````````````````````
                // <dependency>
                // <groupId>com.corpgovernment.framework.apollo</groupId>
                // <artifactId>apollo-client</artifactId>
                // </dependency>
                // ``````````````````````````````````````````````````````````
            } finally {
                DataShardContext.clearTenantId();
            }
        });
        return apolloDataSourceSet;
    }

}
